package texture;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;

public class TextureAtlasSprite {
	private final String iconName;
	private int width;
	private int height;
	private List<int[]> framesTextureData = new ArrayList<>();
	private int frameCounter;
	private int tickCounter;
	private AnimationMetadataSection animationMetadata;
	private int originX;
	private int originY;
	private boolean rotated;
	private float minU;
	private float maxU;
	private float minV;
	private float maxV;

	public TextureAtlasSprite(String par1Str) {
		this.iconName = par1Str;
	}

	public void setIconWidth(int par1) {
		this.width = par1;
	}

	public void setIconHeight(int par1) {
		this.height = par1;
	}

	public void setFramesTextureData(List<int[]> par1List) {
		this.framesTextureData = par1List;
	}

	public boolean load(ResourceManager manager, ResourceLocation location) throws IOException {
		loadSprite(manager.getResource(location));
		return true;
	}

	private void loadSprite(Resource par1Resource) throws IOException {
		this.resetSprite();
		InputStream inputstream = par1Resource.getInputStream();
		BufferedImage bufferedimage = ImageIO.read(inputstream);
		this.height = bufferedimage.getHeight();
		this.width = bufferedimage.getWidth();
		int[] aint = new int[this.height * this.width];
		bufferedimage.getRGB(0, 0, this.width, this.height, aint, 0, this.width);
		
		AnimationMetadataSection animationmetadatasection = (AnimationMetadataSection) par1Resource.getMetadata("animation");
		if (animationmetadatasection == null) {
			if (this.height != this.width) {
				throw new RuntimeException("broken aspect ratio and not an animation");
			}

			this.framesTextureData.add(aint);
		} else {
			int i = this.height / this.width;
			int j = this.width;
			int k = this.width;
			this.height = this.width;
			int l;

			if (animationmetadatasection.getFrameCount() > 0) {
				Iterator<Integer> iterator = animationmetadatasection.getFrameIndexSet().iterator();

				while (iterator.hasNext()) {
					l = ((Integer) iterator.next()).intValue();

					if (l >= i) {
						throw new RuntimeException("invalid frameindex " + l);
					}

					this.allocateFrameTextureData(l);
					this.framesTextureData.set(l, getFrameTextureData(aint, j, k, l));
				}

				this.animationMetadata = animationmetadatasection;
			} else {
				ArrayList<AnimationFrame> arraylist = new ArrayList<>();

				for (l = 0; l < i; ++l) {
					this.framesTextureData.add(getFrameTextureData(aint, j, k, l));
					arraylist.add(new AnimationFrame(l, -1));
				}

				this.animationMetadata = new AnimationMetadataSection(arraylist, this.width, this.height, animationmetadatasection.getFrameTime());
			}
		}
	}

	public void updateAnimation() {
		++this.tickCounter;

		if (this.tickCounter >= this.animationMetadata.getFrameTimeSingle(this.frameCounter)) {
			int i = this.animationMetadata.getFrameIndex(this.frameCounter);
			int j = this.animationMetadata.getFrameCount() == 0 ? this.framesTextureData.size() : this.animationMetadata.getFrameCount();
			this.frameCounter = (this.frameCounter + 1) % j;
			this.tickCounter = 0;
			int k = this.animationMetadata.getFrameIndex(this.frameCounter);

			if (i != k && k >= 0 && k < this.framesTextureData.size()) {
				TextureUtil.uploadTextureSub((int[]) this.framesTextureData.get(k), this.width, this.height, this.originX, this.originY, false, false);
			}
		}
	}
	
	private void allocateFrameTextureData(int par1) {
		if (this.framesTextureData.size() <= par1) {
			for (int j = this.framesTextureData.size(); j <= par1; ++j) {
				this.framesTextureData.add((int[]) null);
			}
		}
	}

	private static int[] getFrameTextureData(int[] par0ArrayOfInteger, int par1, int par2, int par3) {
		int[] aint1 = new int[par1 * par2];
		System.arraycopy(par0ArrayOfInteger, par3 * aint1.length, aint1, 0, aint1.length);
		return aint1;
	}

	private void resetSprite() {
		this.animationMetadata = null;
		this.setFramesTextureData(new ArrayList<int[]>());
		// this.frameCounter = 0;
		// this.tickCounter = 0;
	}

	public int getIconWidth() {
		return this.width;
	}

	public int getIconHeight() {
		return this.height;
	}

	public String getIconName() {
		return this.iconName;
	}

	public void initSprite(int par1, int par2, int par3, int par4, boolean par5) {
		this.originX = par3;
		this.originY = par4;
		this.rotated = par5;
		float f0 = (float) (0.009999999776482582D / (double) par1);
		float f1 = (float) (0.009999999776482582D / (double) par2);

		this.minU = (float) par3 / (float) ((double) par1) + f0;
		this.maxU = (float) (par3 + this.width) / (float) ((double) par1) - f0;

		this.minV = (float) par4 / (float) par2 + f1;
		this.maxV = (float) (par4 + this.height) / (float) par2 - f1;
	}

	public int[] getFrameTextureData(int par1) {
		return (int[]) this.framesTextureData.get(par1);
	}

	public int getOriginX() {
		return this.originX;
	}

	public int getOriginY() {
		return this.originY;
	}

	public boolean hasAnimationMetadata() {
		return this.animationMetadata != null;
	}

	public void clearFramesTextureData() {
		this.framesTextureData.clear();
	}

	public void copyFrom(TextureAtlasSprite par1TextureAtlasSprite) {
		this.originX = par1TextureAtlasSprite.originX;
		this.originY = par1TextureAtlasSprite.originY;
		this.width = par1TextureAtlasSprite.width;
		this.height = par1TextureAtlasSprite.height;
		this.rotated = par1TextureAtlasSprite.rotated;
		this.minU = par1TextureAtlasSprite.minU;
		this.maxU = par1TextureAtlasSprite.maxU;
		this.minV = par1TextureAtlasSprite.minV;
		this.maxV = par1TextureAtlasSprite.maxV;
	}
}
